home *** CD-ROM | disk | FTP | other *** search
/ Aminet 45 / Aminet 45 (2001)(GTI - Schatztruhe)[!][Oct 2001].iso / Aminet / gfx / x11 / x3270_3_2_16.lha / amiga_src / actions.c < prev    next >
C/C++ Source or Header  |  2009-02-27  |  18KB  |  683 lines

  1. /*
  2.  * Modifications Copyright 1993, 1994, 1995, 1999, 2000 by Paul Mattes.
  3.  * Original X11 Port Copyright 1990 by Jeff Sparkes.
  4.  *  Permission to use, copy, modify, and distribute this software and its
  5.  *  documentation for any purpose and without fee is hereby granted,
  6.  *  provided that the above copyright notice appear in all copies and that
  7.  *  both that copyright notice and this permission notice appear in
  8.  *  supporting documentation.
  9.  *
  10.  * Copyright 1989 by Georgia Tech Research Corporation, Atlanta, GA 30332.
  11.  *  All Rights Reserved.  GTRC hereby grants public use of this software.
  12.  *  Derivative works based on this software must incorporate this copyright
  13.  *  notice.
  14.  */
  15.  
  16. /*
  17.  *    actions.c
  18.  *        The X actions table and action debugging code.
  19.  */
  20.  
  21. #include "globals.h"
  22. #include "appres.h"
  23.  
  24. #include "actionsc.h"
  25. #include "hostc.h"
  26. #include "keymapc.h"
  27. #include "kybdc.h"
  28. #include "macrosc.h"
  29. #include "popupsc.h"
  30. #include "printc.h"
  31. #include "selectc.h"
  32. #include "trace_dsc.h"
  33. #include "utilc.h"
  34. #include "xioc.h"
  35.  
  36. #if defined(X3270_FT) /*[*/
  37. #include "ftc.h"
  38. #endif /*]*/
  39. #if defined(X3270_DISPLAY) /*[*/
  40. #include "keypadc.h"
  41. #include "menubarc.h"
  42. #endif /*]*/
  43. #if defined(X3270_DISPLAY) || defined(C3270) /*[*/
  44. #include "screenc.h"
  45. #endif /*]*/
  46.  
  47. #if defined(X3270_TRACE) && defined(X3270_DISPLAY) /*[*/
  48. #include <X11/keysym.h>
  49.  
  50. #define MODMAP_SIZE    8
  51. #define MAP_SIZE    13
  52. #define MAX_MODS_PER    4
  53. static struct {
  54.         const char *name[MAX_MODS_PER];
  55.         unsigned int mask;
  56. } skeymask[MAP_SIZE] = { 
  57.     { { "Shift" }, ShiftMask },
  58.     { { (char *)NULL } /* Lock */, LockMask, },
  59.     { { "Ctrl" }, ControlMask },
  60.     { { (char *)NULL }, Mod1Mask },
  61.     { { (char *)NULL }, Mod2Mask },
  62.     { { (char *)NULL }, Mod3Mask },
  63.     { { (char *)NULL }, Mod4Mask },
  64.     { { (char *)NULL }, Mod5Mask },
  65.     { { "Button1" }, Button1Mask },
  66.     { { "Button2" }, Button2Mask },
  67.     { { "Button3" }, Button3Mask },
  68.     { { "Button4" }, Button4Mask },
  69.     { { "Button5" }, Button5Mask }
  70. };
  71. static Boolean know_mods = False;
  72. #endif /*]*/
  73.  
  74. XtActionsRec actions[] = {
  75. #if defined(X3270_DISPLAY) /*[*/
  76.     { "AltCursor",      AltCursor_action },
  77. #endif /*]*/
  78. #if defined(X3270_DISPLAY) || defined(C3270) /*[*/
  79.     { "Compose",        Compose_action },
  80. #endif /*]*/
  81. #if defined(X3270_DISPLAY) /*[*/
  82.     { "Cut",        Cut_action },
  83.     { "Default",        Default_action },
  84.     { "HandleMenu",        HandleMenu_action },
  85.     { "HardPrint",        PrintText_action },
  86.     { "HexString",        HexString_action },
  87.     { "Info",        Info_action },
  88.     { "Keymap",        TemporaryKeymap_action },
  89.     { PA_PFX "ConfigureNotify", PA_ConfigureNotify_action },
  90.     { PA_END,        PA_End_action },
  91. #endif /*]*/
  92. #if defined(C3270) /*[*/
  93.     { "Escape",        Escape_action },
  94. #endif /*]*/
  95. #if defined(X3270_DISPLAY) /*[*/
  96.     { PA_PFX "EnterLeave",    PA_EnterLeave_action },
  97.     { PA_PFX "Expose",    PA_Expose_action },
  98.     { PA_PFX "Focus",    PA_Focus_action },
  99.     { PA_PFX "GraphicsExpose", PA_GraphicsExpose_action },
  100.     { PA_PFX "KeymapNotify", PA_KeymapNotify_action },
  101. # if defined(X3270_TRACE) /*[*/
  102.     { PA_KEYMAP_TRACE,    PA_KeymapTrace_action },
  103. # endif /*]*/
  104. # if defined(X3270_KEYPAD) /*[*/
  105.     { PA_PFX "ReparentNotify", PA_ReparentNotify_action },
  106. # endif /*]*/
  107.     { PA_PFX "Shift",    PA_Shift_action },
  108.     { PA_PFX "StateChanged", PA_StateChanged_action },
  109.     { PA_PFX "VisibilityNotify",PA_VisibilityNotify_action },
  110.     { PA_PFX "WMProtocols",    PA_WMProtocols_action },
  111.     { PA_PFX "confirm",    PA_confirm_action },
  112.     { "PrintText",        PrintText_action },
  113.     { "PrintWindow",    PrintWindow_action },
  114. #endif /*]*/
  115. #if defined(X3270_DISPLAY) || defined(C3270) /*[*/
  116.     { "Flip",        Flip_action },
  117.     { "Redraw",        Redraw_action },
  118. #endif /*]*/
  119. #if defined(X3270_DISPLAY) /*[*/
  120.     { "SetFont",        SetFont_action },
  121.     { "TemporaryKeymap",    TemporaryKeymap_action },
  122. # if defined(X3270_FT) && defined(X3270_MENUS) /*[*/
  123.     { PA_PFX "dialog-next",    PA_dialog_next_action },
  124.     { PA_PFX "dialog-focus", PA_dialog_focus_action },
  125. # endif /*]*/
  126.     { "insert-selection",    insert_selection_action },
  127.     { "move-select",    move_select_action },
  128.     { "select-end",        select_end_action },
  129.     { "select-extend",    select_extend_action },
  130.     { "select-start",    select_start_action },
  131.     { "set-select",        set_select_action },
  132.     { "start-extend",    start_extend_action },
  133. #endif /*]*/
  134. #if defined(X3270_SCRIPT) /*[*/
  135.     { "AnsiText",        AnsiText_action },
  136. #endif /*]*/
  137.     { "Ascii",        Ascii_action },
  138.     { "AsciiField",        AsciiField_action },
  139.     { "Attn",        Attn_action },
  140.     { "BackSpace",        BackSpace_action },
  141.     { "BackTab",        BackTab_action },
  142.     { "CircumNot",        CircumNot_action },
  143.     { "Clear",        Clear_action },
  144. #if defined(C3270) /*[*/
  145.     { "Close",        Disconnect_action },
  146. #endif /*]*/
  147. #if defined(X3270_SCRIPT) /*[*/
  148.     { "CloseScript",    CloseScript_action },
  149. #endif /*]*/
  150.     { "Connect",        Connect_action },
  151. #if defined(X3270_SCRIPT) /*[*/
  152.     { "ContinueScript",    ContinueScript_action },
  153. #endif /*]*/
  154.     { "CursorSelect",    CursorSelect_action },
  155.     { "Delete",         Delete_action },
  156.     { "DeleteField",    DeleteField_action },
  157.     { "DeleteWord",        DeleteWord_action },
  158.     { "Disconnect",        Disconnect_action },
  159.     { "Down",        Down_action },
  160.     { "Dup",        Dup_action },
  161.     { "Ebcdic",        Ebcdic_action },
  162.     { "EbcdicField",    EbcdicField_action },
  163.     { "Enter",        Enter_action },
  164.     { "Erase",        Erase_action },
  165.     { "EraseEOF",        EraseEOF_action },
  166.     { "EraseInput",        EraseInput_action },
  167. #if defined(X3270_SCRIPT) /*[*/
  168.     { "Execute",        Execute_action },
  169.     { "Expect",        Expect_action },
  170. #endif /*]*/
  171.     { "FieldEnd",        FieldEnd_action },
  172.     { "FieldMark",        FieldMark_action },
  173.     { "FieldExit",        FieldExit_action },
  174.     { "HexString",        HexString_action},
  175. #if defined(C3270) /*[*/
  176.     { "Help",        Help_action},
  177. #endif/*]*/
  178.     { "Home",        Home_action },
  179.     { "Insert",        Insert_action },
  180.     { "Interrupt",        Interrupt_action },
  181.     { "Key",        Key_action },
  182. #if defined(X3270_DISPLAY) /*[*/
  183.     { "KybdSelect",        KybdSelect_action },
  184. #endif /*]*/
  185.     { "Left",        Left_action },
  186.     { "Left2",         Left2_action },
  187. #if defined(X3270_SCRIPT) /*[*/
  188.     { "Macro",         Macro_action },
  189. #endif /*]*/
  190.     { "MonoCase",        MonoCase_action },
  191. #if defined(X3270_DISPLAY) /*[*/
  192.     { "MouseSelect",    MouseSelect_action },
  193. #endif /*]*/
  194.     { "MoveCursor",        MoveCursor_action },
  195.     { "Newline",        Newline_action },
  196.     { "NextWord",        NextWord_action },
  197. #if defined(C3270) /*[*/
  198.     { "Open",        Connect_action },
  199. #endif /*]*/
  200.     { "PA",            PA_action },
  201.     { "PF",            PF_action },
  202. #if defined(X3270_SCRIPT) /*[*/
  203.     { "PauseScript",    PauseScript_action },
  204. #endif /*]*/
  205.     { "PreviousWord",    PreviousWord_action },
  206. #if defined(X3270_SCRIPT) && defined(X3270_PRINTER) /*[*/
  207.     { "Printer",        Printer_action },
  208. #endif /*]*/
  209.     { "Quit",        Quit_action },
  210. #if defined(X3270_MENUS) /*[*/
  211.     { "Reconnect",        Reconnect_action },
  212. #endif /*]*/
  213.     { "Reset",        Reset_action },
  214.     { "Right",        Right_action },
  215.     { "Right2",        Right2_action },
  216. #if defined(X3270_SCRIPT) /*[*/
  217.     { "Script",        Script_action },
  218. #endif /*]*/
  219. #if defined(C3270) /*[*/
  220.     { "Show",        Show_action },
  221. #endif/*]*/
  222. #if defined(X3270_SCRIPT) || defined(TCL3270) /*[*/
  223.     { "Snap",        Snap_action },
  224. #endif /*]*/
  225. #if defined(TCL3270) /*[*/
  226.     { "Status",        Status_action },
  227. #endif /*]*/
  228.     { "String",        String_action },
  229.     { "SysReq",        SysReq_action },
  230.     { "Tab",        Tab_action },
  231.     { "ToggleInsert",    ToggleInsert_action },
  232.     { "ToggleReverse",    ToggleReverse_action },
  233. #if defined(C3270) /*[*/
  234.     { "Trace",        Trace_action },
  235. #endif/*]*/
  236. #if defined(X3270_FT) /*[*/
  237.     { "Transfer",        Transfer_action },
  238. #endif /*]*/
  239. #if defined(X3270_DISPLAY) /*[*/
  240.     { "Unselect",        Unselect_action },
  241. #endif /*]*/
  242.     { "Up",            Up_action },
  243. #if defined(X3270_SCRIPT) || defined(TCL3270) /*[*/
  244.     { "Wait",        Wait_action },
  245. #endif /*]*/
  246.     { "ignore",        ignore_action }
  247. };
  248.  
  249. int actioncount = XtNumber(actions);
  250.  
  251. enum iaction ia_cause;
  252. const char *ia_name[] = {
  253.     "String", "Paste", "Screen redraw", "Keypad", "Default", "Key",
  254.     "Macro", "Script", "Peek", "Typeahead", "File transfer", "Command",
  255.     "Keymap"
  256. };
  257.  
  258. /*
  259.  * Return a name for an action.
  260.  */
  261. const char *
  262. action_name(XtActionProc action)
  263. {
  264.     register int i;
  265.  
  266.     for (i = 0; i < actioncount; i++)
  267.         if (actions[i].proc == action)
  268.             return actions[i].string;
  269.     return "(unknown)";
  270. }
  271.  
  272. #if defined(X3270_DISPLAY) && defined(X3270_TRACE) /*[*/
  273. /*
  274.  * Search the modifier map to learn the modifier bits for Meta, Alt, Hyper and
  275.  *  Super.
  276.  */
  277. static void
  278. learn_modifiers(void)
  279. {
  280.     XModifierKeymap *mm;
  281.     int i, j, k;
  282.  
  283.     mm = XGetModifierMapping(display);
  284.  
  285.     for (i = 0; i < MODMAP_SIZE; i++) {
  286.         for (j = 0; j < mm->max_keypermod; j++) {
  287.             KeyCode kc;
  288.             const char *name = CN;
  289.  
  290.             kc = mm->modifiermap[(i * mm->max_keypermod) + j];
  291.             if (!kc)
  292.                 continue;
  293.  
  294.             switch(XKeycodeToKeysym(display, kc, 0)) {
  295.                 case XK_Meta_L:
  296.                 case XK_Meta_R:
  297.                 name = "Meta";
  298.                 break;
  299.                 case XK_Alt_L:
  300.                 case XK_Alt_R:
  301.                 name = "Alt";
  302.                 break;
  303.                 case XK_Super_L:
  304.                 case XK_Super_R:
  305.                 name = "Super";
  306.                 break;
  307.                 case XK_Hyper_L:
  308.                 case XK_Hyper_R:
  309.                 name = "Hyper";
  310.                 break;
  311.                 default:
  312.                 break;
  313.             }
  314.             if (name == CN)
  315.                 continue;
  316.  
  317.             for (k = 0; k < MAX_MODS_PER; k++) {
  318.                 if (skeymask[i].name[k] == CN)
  319.                     break;
  320.                 else if (!strcmp(skeymask[i].name[k], name))
  321.                     k = MAX_MODS_PER;
  322.             }
  323.             if (k >= MAX_MODS_PER)
  324.                 continue;
  325.             skeymask[i].name[k] = name;
  326.         }
  327.     }
  328. }
  329.  
  330. /*
  331.  * Return the symbolic name for the modifier combination (i.e., "Meta" instead
  332.  * of "Mod2".  Note that because it is possible to map multiple keysyms to the
  333.  * same modifier bit, the answer may be ambiguous; we return the combinations
  334.  * iteratively.
  335.  */
  336. static char *
  337. key_symbolic_state(unsigned int state, int *iteration)
  338. {
  339.     static char rs[64];
  340.     static int ix[MAP_SIZE];
  341.     static int ix_ix[MAP_SIZE];
  342.     static int n_ix = 0;
  343.     static int leftover = 0;
  344.     const char *comma = "";
  345.     int i;
  346.  
  347.     if (!know_mods) {
  348.         learn_modifiers();
  349.         know_mods = True;
  350.     }
  351.  
  352.     if (*iteration == 0) {
  353.         /* First time, build the table. */
  354.         n_ix = 0;
  355.         for (i = 0; i < MAP_SIZE; i++) {
  356.             if (skeymask[i].name[0] != CN &&
  357.                 (state & skeymask[i].mask)) {
  358.                 ix[i] = 0;
  359.                 state &= ~skeymask[i].mask;
  360.                 ix_ix[n_ix++] = i;
  361.             } else
  362.                 ix[i] = MAX_MODS_PER;
  363.         }
  364.         leftover = state;
  365.     }
  366.  
  367.     /* Construct this result. */
  368.     rs[0] = '\0';
  369.     for (i = 0; i < n_ix;  i++) {
  370.         (void) strcat(rs, comma);
  371.         (void) strcat(rs, skeymask[ix_ix[i]].name[ix[ix_ix[i]]]);
  372.         comma = " ";
  373.     }
  374.     if (leftover)
  375.         (void) sprintf(strchr(rs, '\0'), "%s?%d", comma, state);
  376.  
  377.     /*
  378.      * Iterate to the next.
  379.      * This involves treating each slot like an n-ary number, where n is
  380.      * the number of elements in the slot, iterating until the highest-
  381.      * ordered slot rolls back over to 0.
  382.      */
  383.     if (n_ix) {
  384.         i = n_ix - 1;
  385.         ix[ix_ix[i]]++;
  386.         while (i >= 0 &&
  387.                (ix[ix_ix[i]] >= MAX_MODS_PER ||
  388.             skeymask[ix_ix[i]].name[ix[ix_ix[i]]] == CN)) {
  389.             ix[ix_ix[i]] = 0;
  390.             i = i - 1;
  391.             if (i >= 0)
  392.                 ix[ix_ix[i]]++;
  393.         }
  394.         *iteration = i >= 0;
  395.     } else
  396.         *iteration = 0;
  397.  
  398.     return rs;
  399. }
  400.  
  401. #if defined(VERBOSE_EVENTS) /*[*/
  402. static char *
  403. key_state(unsigned int state)
  404. {
  405.     static char rs[64];
  406.     const char *comma = "";
  407.     static struct {
  408.         const char *name;
  409.         unsigned int mask;
  410.     } keymask[] = {
  411.         { "Shift", ShiftMask },
  412.         { "Lock", LockMask },
  413.         { "Control", ControlMask },
  414.         { "Mod1", Mod1Mask },
  415.         { "Mod2", Mod2Mask },
  416.         { "Mod3", Mod3Mask },
  417.         { "Mod4", Mod4Mask },
  418.         { "Mod5", Mod5Mask },
  419.         { "Button1", Button1Mask },
  420.         { "Button2", Button2Mask },
  421.         { "Button3", Button3Mask },
  422.         { "Button4", Button4Mask },
  423.         { "Button5", Button5Mask },
  424.         { CN, 0 },
  425.     };
  426.     int i;
  427.  
  428.     rs[0] = '\0';
  429.     for (i = 0; keymask[i].name; i++) {
  430.         if (state & keymask[i].mask) {
  431.             (void) strcat(rs, comma);
  432.             (void) strcat(rs, keymask[i].name);
  433.             comma = "|";
  434.             state &= ~keymask[i].mask;
  435.         }
  436.     }
  437.     if (!rs[0])
  438.         (void) sprintf(rs, "%d", state);
  439.     else if (state)
  440.         (void) sprintf(strchr(rs, '\0'), "%s?%d", comma, state);
  441.     return rs;
  442. }
  443. #endif /*]*/
  444. #endif /*]*/
  445.  
  446. /*
  447.  * Check the number of argument to an action, and possibly pop up a usage
  448.  * message.
  449.  *
  450.  * Returns 0 if the argument count is correct, -1 otherwise.
  451.  */
  452. int
  453. check_usage(XtActionProc action, Cardinal nargs, Cardinal nargs_min,
  454.     Cardinal nargs_max)
  455. {
  456.     if (nargs >= nargs_min && nargs <= nargs_max)
  457.         return 0;
  458.     if (nargs_min == nargs_max)
  459.         popup_an_error("%s requires %d argument%s",
  460.             action_name(action), nargs_min, nargs_min == 1 ? "" : "s");
  461.     else
  462.         popup_an_error("%s requires %d or %d arguments",
  463.             action_name(action), nargs_min, nargs_max);
  464.     return -1;
  465. }
  466.  
  467. /*
  468.  * Display an action debug message
  469.  */
  470. #if defined(X3270_TRACE) /*[*/
  471.  
  472. #define KSBUF    256
  473. void
  474. action_debug(XtActionProc action, XEvent *event, String *params,
  475.     Cardinal *num_params)
  476. {
  477.     Cardinal i;
  478. #if defined(X3270_DISPLAY) /*[*/
  479.     XKeyEvent *kevent;
  480.     KeySym ks;
  481.     XButtonEvent *bevent;
  482.     XMotionEvent *mevent;
  483.     XConfigureEvent *cevent;
  484.     XClientMessageEvent *cmevent;
  485.     XExposeEvent *exevent;
  486.     const char *press = "Press";
  487.     const char *direction = "Down";
  488.     char dummystr[KSBUF+1];
  489.     char *atom_name;
  490.     int ambiguous = 0;
  491.     int state;
  492.     const char *symname = "";
  493.     char snbuf[11];
  494. #endif /*]*/
  495.  
  496.     if (!toggled(EVENT_TRACE))
  497.         return;
  498.     if (event == (XEvent *)NULL) {
  499.         (void) fprintf(tracef, " %s", ia_name[(int)ia_cause]);
  500.     }
  501. #if defined(X3270_DISPLAY) /*[*/
  502.     else switch (event->type) {
  503.         case KeyRelease:
  504.         press = "Release";
  505.         case KeyPress:
  506.         kevent = (XKeyEvent *)event;
  507.         (void) XLookupString(kevent, dummystr, KSBUF, &ks, NULL);
  508.         state = kevent->state;
  509.         /*
  510.          * If the keysym is a printable ASCII character, ignore the
  511.          * Shift key.
  512.          */
  513.         if (ks != ' ' && !(ks & ~0xff) && isprint(ks))
  514.             state &= ~ShiftMask;
  515.         if (ks == NoSymbol)
  516.             symname = "NoSymbol";
  517.         else if ((symname = XKeysymToString(ks)) == CN) {
  518.             (void) sprintf(snbuf, "0x%lx", (unsigned long)ks);
  519.             symname = snbuf;
  520.         }
  521.         do {
  522.             int was_ambiguous = ambiguous;
  523.  
  524.             (void) fprintf(tracef, "%s ':%s<Key%s>%s'",
  525.                 was_ambiguous? " or": "Event",
  526.                 key_symbolic_state(state, &ambiguous),
  527.                 press,
  528.                 symname);
  529.         } while (ambiguous);
  530.         /*
  531.          * If the keysym is an alphanumeric ASCII character, show the
  532.          * case-insensitive alternative, sans the colon.
  533.          */
  534.         if (!(ks & ~0xff) && isalpha(ks)) {
  535.             ambiguous = 0;
  536.             do {
  537.                 int was_ambiguous = ambiguous;
  538.  
  539.                 (void) fprintf(tracef, " %s '%s<Key%s>%s'",
  540.                     was_ambiguous? "or":
  541.                         "(case-insensitive:",
  542.                     key_symbolic_state(state, &ambiguous),
  543.                     press,
  544.                     symname);
  545.             } while (ambiguous);
  546.             (void) fprintf(tracef, ")");
  547.         }
  548. #if defined(VERBOSE_EVENTS) /*[*/
  549.         (void) fprintf(tracef,
  550.             "\nKey%s [state %s, keycode %d, keysym 0x%lx \"%s\"]",
  551.                 press, key_state(kevent->state),
  552.                 kevent->keycode, ks,
  553.                 symname);
  554. #endif /*]*/
  555.         break;
  556.         case ButtonRelease:
  557.         press = "Release";
  558.         direction = "Up";
  559.         case ButtonPress:
  560.         bevent = (XButtonEvent *)event;
  561.         do {
  562.             int was_ambiguous = ambiguous;
  563.  
  564.             (void) fprintf(tracef, "%s '%s<Btn%d%s>'",
  565.                 was_ambiguous? " or": "Event",
  566.                 key_symbolic_state(bevent->state, &ambiguous),
  567.                 bevent->button,
  568.                 direction);
  569.         } while (ambiguous);
  570. #if defined(VERBOSE_EVENTS) /*[*/
  571.         (void) fprintf(tracef,
  572.             "\nButton%s [state %s, button %d]",
  573.             press, key_state(bevent->state),
  574.             bevent->button);
  575. #endif /*]*/
  576.         break;
  577.         case MotionNotify:
  578.         mevent = (XMotionEvent *)event;
  579.         do {
  580.             int was_ambiguous = ambiguous;
  581.  
  582.             (void) fprintf(tracef, "%s '%s<Motion>'",
  583.                 was_ambiguous? " or": "Event",
  584.                 key_symbolic_state(mevent->state, &ambiguous));
  585.         } while (ambiguous);
  586. #if defined(VERBOSE_EVENTS) /*[*/
  587.         (void) fprintf(tracef,
  588.             "\nMotionNotify [state %s]", key_state(mevent->state));
  589. #endif /*]*/
  590.         break;
  591.         case EnterNotify:
  592.         (void) fprintf(tracef, "EnterNotify");
  593.         break;
  594.         case LeaveNotify:
  595.         (void) fprintf(tracef, "LeaveNotify");
  596.         break;
  597.         case FocusIn:
  598.         (void) fprintf(tracef, "FocusIn");
  599.         break;
  600.         case FocusOut:
  601.         (void) fprintf(tracef, "FocusOut");
  602.         break;
  603.         case KeymapNotify:
  604.         (void) fprintf(tracef, "KeymapNotify");
  605.         break;
  606.         case Expose:
  607.         exevent = (XExposeEvent *)event;
  608.         (void) fprintf(tracef, "Expose [%dx%d+%d+%d]",
  609.             exevent->width, exevent->height, exevent->x, exevent->y);
  610.         break;
  611.         case PropertyNotify:
  612.         (void) fprintf(tracef, "PropertyNotify");
  613.         break;
  614.         case ClientMessage:
  615.         cmevent = (XClientMessageEvent *)event;
  616.         atom_name = XGetAtomName(display, (Atom)cmevent->data.l[0]);
  617.         (void) fprintf(tracef, "ClientMessage [%s]",
  618.             (atom_name == CN) ? "(unknown)" : atom_name);
  619.         break;
  620.         case ConfigureNotify:
  621.         cevent = (XConfigureEvent *)event;
  622.         (void) fprintf(tracef, "ConfigureNotify [%dx%d+%d+%d]",
  623.             cevent->width, cevent->height, cevent->x, cevent->y);
  624.         break;
  625.         default:
  626.         (void) fprintf(tracef, "Event %d", event->type);
  627.         break;
  628.     }
  629.     if (keymap_trace != CN)
  630.         (void) fprintf(tracef, " via %s -> %s(", keymap_trace,
  631.             action_name(action));
  632.     else
  633. #endif /*]*/
  634.         (void) fprintf(tracef, " -> %s(",
  635.             action_name(action));
  636.     for (i = 0; i < *num_params; i++) {
  637.         (void) fprintf(tracef, "%s\"", i ? ", " : "");
  638.         fcatv(tracef, params[i]);
  639.         fputc('"', tracef);
  640.     }
  641.     (void) fprintf(tracef, ")\n");
  642. }
  643.  
  644. #endif /*]*/
  645.  
  646. /*
  647.  * Wrapper for calling an action internally.
  648.  */
  649. void
  650. action_internal(XtActionProc action, enum iaction cause, const char *parm1,
  651.     const char *parm2)
  652. {
  653.     Cardinal count = 0;
  654.     String parms[2];
  655.  
  656.     /* Duplicate the parms, because XtActionProc doesn't grok 'const'. */
  657.     if (parm1 != CN) {
  658.         parms[0] = NewString(parm1);
  659.         count++;
  660.         if (parm2 != CN) {
  661.             parms[1] = NewString(parm2);
  662.             count++;
  663.         }
  664.     }
  665.  
  666.     ia_cause = cause;
  667.     (*action)((Widget) NULL, (XEvent *) NULL,
  668.         count ? parms : (String *) NULL,
  669.         &count);
  670.  
  671.     /* Free the parm copies. */
  672.     switch (count) {
  673.         case 2:
  674.         Free(parms[1]);
  675.         /* fall through... */
  676.         case 1:
  677.         Free(parms[0]);
  678.         break;
  679.         default:
  680.         break;
  681.     }
  682. }
  683.